<!--
 * https://bossanova.uk/jspreadsheet/v4/examples/events
 
    onchange: changed,
    onbeforechange: beforeChange,
    oninsertrow: insertedRow,
    oninsertcolumn: insertedColumn,
    ondeleterow: deletedRow,
    ondeletecolumn: deletedColumn,
    onselection: selectionActive,
    onsort: sort,
    onresizerow: resizeRow,
    onresizecolumn: resizeColumn,
    onmoverow: moveRow,
    onmovecolumn: moveColumn,
    onload: loaded,
    onblur: blur,
    onfocus: focus,
    onpaste: paste,
 * createRow 添加行
 * { type: 'text', title:'Car', width:120 },
 * { type: 'dropdown', title:'Make', width:200, source:[ "Bmw" ] },
 * { type: 'calendar', title:'Available', width:200 },
 * { type: 'image', title:'Photo', width:120 },dropdown
 * { type: 'checkbox', title:'Stock', width:80 },
 * { type: 'numeric', title:'Price', width:100, mask:'$ #.##,00', decimal:',' },
 * { type: 'color', width:100, render:'square', }
-->
<template>
  <div :id="excelId" v-show="tableColumns.length" />
  <a-empty v-if="tableColumns.length === 0" />
</template>
<script>
import Jexcel from 'jexcel'
import 'jexcel/dist/jexcel.css'
import zhCN from 'jexcel/lang/zh_CN'
export default {
  componens: { Jexcel },
  props: {
    excelId: {
      type: String,
      default: 'excel'
    },
    source: {
      type: Array,
      default: () => []
    },
    columns: {
      type: Array,
      default: () => []
    },
    tableWidth: {
      type: String,
      default: ''
    },
    mergeCells: {
      type: Object,
      default: () => {
        return {}
      }
    },
    updateTable: {
      type: Function,
      default: null
    },
    footers: {
      type: Array,
      default: () => []
    },
    deleteLists: {
      type: Array,
      default: () => []
    },
    hightLights: {
      type: Array,
      default: () => []
    },
    editable: {
      type: Boolean,
      default: true
    },
    showSetting: {
      type: Boolean,
      default: false
    },
    cpSizeVos: {
      type: Array,
      default: () => []
    },
    sizeChartData: {
      type: Array,
      default: () => []
    },
    allowInsertColumn: {
      type: Boolean,
      default: false
    },
    allowDeleteColumn: {
      type: Boolean,
      default: false
    },
    setContextMenu: {
      type: Function
    }
  },
  data() {
    return {
      table: null,
      tableData: [],
      tableColumns: this.columns,
      tableStyle: null,
      pasteX: 0,
      pasteY: 0
    }
  },
  watch: {
    source: {
      handler(val) {
        this.tableData = val
        if (this.table) {
          this.table.setData(val)
        }
      },
      immediate: true
    },
    columns: {
      handler(val, oldVal) {
        if (JSON.stringify(val) !== JSON.stringify(oldVal)) {
          this.tableColumns = val
          if (this.table) {
            this.renderTable()
          }
        }
      },
      immediate: true,
      deep: true
    },
    hightLights: {
      handler() {
        if (this.table) {
          this.setStyle()
        }
      },
      immediate: true
    }
  },
  mounted() {
    this.renderTable()
    setTimeout(() => {
      this.setStyle()
    }, 0)
  },
  methods: {
    setHightLight(obj, x, y, color = '#7992cb') {
      const xy = {
        0: 'A',
        1: 'B',
        2: 'C',
        3: 'D',
        4: 'E',
        5: 'F',
        6: 'G',
        7: 'H',
        8: 'I',
        9: 'J',
        10: 'K',
        11: 'L',
        12: 'M',
        13: 'N',
        14: 'O',
        15: 'P',
        16: 'Q',
        17: 'R',
        18: 'S',
        19: 'T',
        20: 'U',
        21: 'V',
        22: 'W',
        23: 'X',
        24: 'Y',
        25: 'Z'
      }
      const cell = `${xy[x]}${y + 1}`
      obj.setStyle(cell, 'background-color', color)
    },
    setStyle() {
      for (const item of this.hightLights) {
        this.setHightLight(
          this.table,
          Number(item.abscissaNumber),
          Number(item.ordinateNumber),
          item.rgb
        )
      }
    },
    computeList(obj, x, y, color = '#7992cb') {
      const selectedContainer = obj.selectedContainer
      const startX = selectedContainer[0]
      const endX = selectedContainer[2]
      const startY = selectedContainer[1]
      const endY = selectedContainer[3]
      if (startX === endX && startY === endY) {
        const measurementChartCode = this.tableColumns[Number(x)].title
        const item = {
          x: Number(x),
          y: Number(y),
          rgb: color,
          measurementChartCode,
          ordinateNumber: Number(y),
          abscissaNumber: Number(x)
        }
        this.$emit('addLight', item)
        this.setHightLight(obj, Number(x), Number(y), color)
      } else {
        for (let i = startX; i <= endX; i++) {
          for (let j = startY; j <= endY; j++) {
            const measurementChartCode = this.tableColumns[Number(i)].title
            const item = {
              x: Number(i),
              y: Number(j),
              rgb: color,
              measurementChartCode,
              ordinateNumber: Number(j),
              abscissaNumber: Number(i)
            }
            this.$emit('addLight', item)
          }
        }
        this.setStyle()
      }
    },
    deleteHightList(obj, x, y) {
      const selectedContainer = obj.selectedContainer
      const startX = selectedContainer[0]
      const endX = selectedContainer[2]
      const startY = selectedContainer[1]
      const endY = selectedContainer[3]
      if (startX === endX && startY === endY) {
        const item = {
          x: Number(x),
          y: Number(y)
        }
        this.$emit('clear', item)
      } else {
        for (let i = startX; i <= endX; i++) {
          for (let j = startY; j <= endY; j++) {
            const item = {
              x: Number(i),
              y: Number(j),
              ordinateNumber: Number(j),
              abscissaNumber: Number(i)
            }
            this.$emit('clear', item)
          }
        }
      }
      for (const item of this.deleteLists) {
        this.setHightLight(
          obj,
          item.abscissaNumber,
          item.ordinateNumber,
          '#ffffff'
        )
      }
      // 清空删除的数据
      this.$emit('empty')
    },
    oneditionendEvent(table, x, y, value) {
      // 触发自动计算
      if (!this.showSetting) return
      const header = table.getHeader([x])
      const headers = table.getHeaders().split(',')
      // console.log(header, headers, x, y, value)
      // 判断是否是条码挡区间范围
      const sizeRangeObj = this.cpSizeVos.find(item => item.size === header)
      if (sizeRangeObj) {
        // 获取要自动带出的列
        const changeColumns = sizeRangeObj.sizeList
        console.log(this.sizeChartData, 'this.sizeChartData')
        console.log(header)
        const baseSize = this.sizeChartData[y].list.filter(
          ite => ite.size === header
        )[0].baseSize
        const baseindex = headers.indexOf(baseSize)
        const baseSizeValue = table.getValueFromCoords(baseindex, y)
        headers.forEach((item, index) => {
          if (changeColumns.includes(item)) {
            // 如果是基码列不自动带出
            if (
              item === baseSize ||
              (!baseSizeValue && baseSizeValue !== 0) ||
              (!value && value !== 0)
            )
              return
            const val = (index - baseindex) * value + baseSizeValue * 1
            table.setValueFromCoords(
              index,
              y,
              Math.round((val + Number.EPSILON) * 10) / 10
            )
          }
        })
      }
      this.baseSizeChange(table, x, y, value)
    },
    baseSizeChange(table, x, y, value) {
      const header = table.getHeader([x])
      const headers = table.getHeaders().split(',')
      const baseSizeObj = this.cpSizeVos.find(item => item.sizeBase === header)
      // 判断是否是基码列
      if (baseSizeObj) {
        const sizerange = baseSizeObj.size
        const sizeRangeindex = headers.indexOf(sizerange)
        // 获取要自动带出的列
        const changeColumns = baseSizeObj.sizeList
        const baseSize = header
        const baseindex = x
        const sizeRangeValue = table.getValueFromCoords(sizeRangeindex, y)
        headers.forEach((item, index) => {
          if (changeColumns.includes(item)) {
            // 如果是基码列不自动带出
            if (
              item === baseSize ||
              (!sizeRangeValue && sizeRangeValue !== 0) ||
              (!value && value !== 0)
            )
              return
            const val = (index - baseindex) * sizeRangeValue + value * 1
            table.setValueFromCoords(
              index,
              y,
              Math.round((val + Number.EPSILON) * 10) / 10
            )
          }
        })
        // 如果当前变动的列包含别的基码，其它列也随之变化
        this.cpSizeVos.forEach(ite => {
          if (
            changeColumns.includes(ite.sizeBase) &&
            ite.sizeBase !== baseSize
          ) {
            const baseIndex = headers.indexOf(ite.sizeBase)
            const currentBasevalue = table.getValueFromCoords(baseIndex, y)
            this.baseSizeChange(table, baseIndex, y, currentBasevalue)
          }
        })
      }
    },
    renderTable() {
      const that = this
      const dom = document.getElementById(this.excelId)
      if (this.table) {
        document.getElementById(this.excelId).innerHTML = ''
      }
      this.table = new Jexcel(dom, {
        data: this.tableData,
        columns: this.tableColumns,
        text: zhCN,
        wordWrap: true,
        tableOverflow: true,
        editable: this.editable,
        tableHeight: '400px',
        tableWidth: this.tableWidth,
        footers: this.footers,
        mergeCells: this.mergeCells,
        updateTable: this.updateTable,
        columnSorting: false,
        columnResize: false,
        allowRenameColumn: false,
        allowDeleteColumn: this.allowDeleteColumn || false,
        allowInsertColumn: this.allowInsertColumn || false,
        allowManualInsertColumn: false,
        onbeforepaste: function (worksheet, data, x, y) {
          that.pasteX = x
          that.pasteY = y
          that.tableStyle = that.table.getStyle()
        },
        onpaste: function (e, value) {
          setTimeout(() => {
            const cells = Object.keys(that.tableStyle)
            for (const cell of cells) {
              that.table.setStyle(cell, 'background-color', '#ffffff')
            }
            that.setStyle()
          }, 0)
          value.forEach((item, index) => {
            item.forEach((val, inde) => {
              console.log(that.pasteX * 1 + inde, that.pasteY * 1 + index, val)
              try {
                that.oneditionendEvent(
                  that.table,
                  that.pasteX * 1 + inde,
                  that.pasteY * 1 + index,
                  val
                )
              } catch (error) {
                console.log(error)
              }
            })
          })
        },
        oneditionend: function (e, obj, x, y, value) {
          that.oneditionendEvent(that.table, x, y, value)
          that.$emit('oneditionend', that.table, x, y, value)
        },
        contextMenu: function (obj, x, y) {
          if (that.setContextMenu) {
            return that.setContextMenu(obj, x, y)
          }
          let items = []
          if (y === null) {
            // Insert a new column
            if (obj.options.allowInsertColumn === true) {
              items.push({
                title: obj.options.text.insertANewColumnBefore,
                onclick: function () {
                  obj.insertColumn(1, parseInt(x), 1)
                }
              })
            }

            if (obj.options.allowInsertColumn === true) {
              items.push({
                title: obj.options.text.insertANewColumnAfter,
                onclick: function () {
                  obj.insertColumn(1, parseInt(x), 0)
                }
              })
            }

            // Delete a column
            if (obj.options.allowDeleteColumn === true) {
              items.push({
                title: obj.options.text.deleteSelectedColumns,
                onclick: function () {
                  obj.deleteColumn(
                    obj.getSelectedColumns().length ? undefined : parseInt(x)
                  )
                }
              })
            }

            // Rename column
            if (obj.options.allowRenameColumn === true) {
              items.push({
                title: obj.options.text.renameThisColumn,
                onclick: function () {
                  obj.setHeader(x)
                }
              })
            }

            // Sorting
            if (obj.options.columnSorting === true) {
              // Line
              items.push({ type: 'line' })

              items.push({
                title: obj.options.text.orderAscending,
                onclick: function () {
                  obj.orderBy(x, 0)
                }
              })
              items.push({
                title: obj.options.text.orderDescending,
                onclick: function () {
                  obj.orderBy(x, 1)
                }
              })
            }
          } else {
            // Insert new row
            if (obj.options.allowInsertRow === true) {
              items.push({
                title: obj.options.text.insertANewRowBefore,
                onclick: function () {
                  obj.insertRow(1, parseInt(y), 1)
                  setTimeout(() => {
                    that.$emit('changeY', y, true)
                    for (const item of that.hightLights) {
                      that.setHightLight(
                        obj,
                        Number(item.abscissaNumber),
                        Number(item.ordinateNumber),
                        item.rgb
                      )
                    }
                  }, 0)
                }
              })
              items.push({
                title: obj.options.text.insertANewRowAfter,
                onclick: function () {
                  obj.insertRow(1, parseInt(y))
                  setTimeout(() => {
                    that.$emit('changeY', y, false)
                    for (const item of that.hightLights) {
                      that.setHightLight(
                        obj,
                        Number(item.abscissaNumber),
                        Number(item.ordinateNumber),
                        item.rgb
                      )
                    }
                  }, 0)
                }
              })
            }

            if (obj.options.allowDeleteRow === true) {
              items.push({
                title: obj.options.text.deleteSelectedRows,
                onclick: function () {
                  obj.deleteRow(
                    obj.getSelectedRows().length ? undefined : parseInt(y)
                  )
                  setTimeout(() => {
                    that.$emit(
                      'deleteLights',
                      Number(y),
                      obj.getSelectedRows().length
                    )
                    for (const item of this.deleteLists) {
                      this.setHightLight(
                        obj,
                        item.abscissaNumber,
                        item.ordinateNumber,
                        '#ffffff'
                      )
                    }
                    // 清空删除的数据
                    this.$emit('empty')
                    for (const item of that.hightLights) {
                      that.setHightLight(
                        obj,
                        Number(item.abscissaNumber),
                        Number(item.ordinateNumber),
                        item.rgb
                      )
                    }
                  }, 0)
                }
              })
            }

            if (x) {
              if (obj.options.allowComments === true) {
                items.push({ type: 'line' })
                const title = obj.records[y][x].getAttribute('title') || ''
                items.push({
                  title: title
                    ? obj.options.text.editComments
                    : obj.options.text.addComments,
                  onclick: function () {
                    obj.setComments(
                      [x, y],
                      prompt(obj.options.text.comments, title)
                    )
                  }
                })

                if (title) {
                  items.push({
                    title: obj.options.text.clearComments,
                    onclick: function () {
                      obj.setComments([x, y], '')
                    }
                  })
                }
              }
            }
          }

          // Line
          items.push({ type: 'line' })

          // Save
          if (obj.options.allowExport) {
            items.push({
              title: obj.options.text.saveAs,
              shortcut: 'Ctrl + S',
              onclick: function () {
                obj.download()
              }
            })
          }

          // // About
          // if (obj.options.about) {
          //   items.push({
          //     title: obj.options.text.about,
          //     onclick: function() {
          //       alert(obj.options.about)
          //     }
          //   })
          // }
          items.push({
            title: '标蓝',
            onclick: function () {
              that.computeList(obj, x, y)
            }
          })
          items.push({
            title: '标黄',
            onclick: function () {
              that.computeList(obj, x, y, '#ffff54')
            }
          })
          items.push({
            title: '去掉高亮',
            onclick: function () {
              that.deleteHightList(obj, x, y)
            }
          })
          if (!this.editable) {
            items = []
          }
          return items
        }
      })
    }
  }
}
</script>
<style lang="scss" scoped>
:deep .resizable tr td {
  background: #d8d5d5;
}
</style>
